package com.xyz;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) throws IOException {

        //构建地图
        Map maps[][] = initMap();
        //初始化怪物
        initMonsters(maps);

        //使用类定义
        //定义玩家对象
        Player p1 = initPlayer(maps);

        //玩家进入地图，找怪、打怪
        cmd_ui(p1,maps);
    }

    // 用户交互逻辑，除了初始化之外的游戏主进程控制，都放在下面方法中
    public static void cmd_ui(Player p,Map[][] maps) throws IOException{
        //定义一个循环，不停的询问用户下一步要干嘛
        do{
            System.out.println("老大，接下来要干啥？");
            System.out.println("请输入下面命令中任意一项：");
            System.out.println("命令：status   功能：查看玩家当前状态");
            System.out.println("命令：travel   功能：在地图上旅行");
            System.out.println("命令：look   功能：看景色");
            System.out.println("命令：fm   功能：find monster 找怪物");
            System.out.println("命令：km   功能：kill monster 打怪物");
            System.out.println("命令：save   功能：存档");
            System.out.println("命令：load   功能：读档");
            System.out.println("命令：quit   功能：退出游戏");
            //获取用户输入的命令
            Scanner sc = new Scanner(System.in);
            String next_move= sc.next();
            //进入分支，根据命令来进行相应的操作
            switch (next_move){
                //显示当前玩家状态
                case "status":
                    p.print();
                    break;
                //旅行
                case "travel":
                    p.do_travel(maps);
                    break;
                //看当前所在位置环境
                case "look":
                    p.look(maps);
                    break;
                //查看当前地图怪物信息
                case "fm":
                    p.findMonster(maps);
                    break;
                //打怪
                case "km":
                    //获取玩家所在的地图
                    Map m = maps[p.getX()][p.getY()];
                    p.km(m);
                    if(p.getHp()<=0){
                        System.out.println("Game Over!");
                        return;
                    }
                    break;
                //存档
                case "save":
                    //p是当前内存中的玩家对象
                    savePlayer(p);
                    break;
                //读档
                case "load":
                    loadPlayer(p);
                    break;
                case "quit":
                    //退出游戏分支
                    System.out.println("Game Over!");
                    //用return 退出当前方法
                    return;
                default:
                    System.out.println("老大，你不认识字吗？敢敲个正确的命令不？");
            }

        }while (true);

    }

    // 存储玩家信息到文件中
    public static void savePlayer(Player p) throws IOException {
        try (Writer writer = new OutputStreamWriter(new FileOutputStream("player_save.txt"), "UTF-8")) {
            //我的拼接方式，一个字段名配上一个字段值，中间用 ; 隔开
            String playerState = "name:"+p.getName()+";";
            playerState+="hp:"+p.getHp()+";";
            playerState+="ap:"+p.getAp()+";";
            playerState+="sp:"+p.getSp()+";";
            playerState+="x:"+p.getX()+";";
            playerState+="y:"+p.getY()+";";
            //playerState+="skill:"+p.getSkills()+";";
            writer.write(playerState); // 写入String
        }
    }

    // 读档方法
    public static void loadPlayer(Player p) throws IOException {
        //创建 reader 对象
        try (Reader reader = new InputStreamReader(new FileInputStream("player_save.txt"), "UTF-8")) {
            // 创建缓冲区，可以一次将文件中内容读入内存缓冲区中
            char[] buffer = new char[1000];
            int n;
            String s="";
            //读取文件内容到缓冲区，并转换为字符串
            while ((n = reader.read(buffer)) != -1) {
                //一共读了多少个字符
                System.out.println("read " + n + " chars.");
                //将缓冲区内容存入字符串，方便后续处理，并去除空字符
                s = String.valueOf(buffer).trim();
                //打印字符串
                System.out.println(s);
            }
            //分割字符串，并将其中信息读入 p 当前玩家对象汇总
            if(s!=""){
                //创建 HashMap 对象，来存储玩家字段信息，字段名为key，字段值是 value
                HashMap<String,String> hashMap = new HashMap<>();
                // 将字符串按 ; 分割,存入字符数组
                String[] strArray = s.split(";");
                // 通过遍历，将字符串数组中的每一项，转换为 HashMap 中的一个键值对
                for(String pair:strArray) {
                    //将字符串按 : 分割，区分 key 和 value
                    String[] subArray = pair.split(":");
                    // 将子字符数组中的索引0 当做 Key， 索引1 当做 value 建立 HashMap 中的各个项
                    hashMap.put(subArray[0], subArray[1]);
                }
                //设置内存中当前玩家对象的各个字段值
                p.setName(hashMap.get("name"));
                p.setX(Integer.parseInt(hashMap.get("x")));
                p.setY(Integer.parseInt(hashMap.get("y")));
                p.setHp(Integer.parseInt(hashMap.get("hp")));
                p.setAp(Integer.parseInt(hashMap.get("ap")));
                p.setSp(Integer.parseInt(hashMap.get("sp")));
                System.out.println("读档成功！");
            }
        }
    }

    //初始化地图的方法
    public static Map[][] initMap(){

        System.out.println("初始化地图开始........");

        Map m1 = new Map("天竺","只见天上万道佛光，飞天仙女吹奏着无上仙音，各种瑞兽灵怪四处游走",0,0);
        Map m2 = new Map("北冥冰国","放眼处万里冰封，寒风呼啸，鹅毛大雪随风飞舞",1,0);
        Map m3 = new Map("花果山","苍天巨树林立，奇花异果密布，到处都有猴子窜来窜去",2,0);
        Map m4 = new Map("火焰山","满目赤红的世界，空气都在热力下扭曲，远处大山上还冒起冲天大火",0,1);
        Map m5 = new Map("东土大唐","街道宽敞整洁，店铺鳞次栉比，车马如龙，行人似海",1,1);
        Map m6 = new Map("龙宫","整个如水晶世界，各种游鱼水怪传游不息，远处一个金碧辉煌的宫殿，上写两个大字：水晶宫！",2,1);
        Map m7 = new Map("盘丝洞","黑色洞口阴风不断，深不见底，四处布满蛛丝，还有无数小蛛爬来爬去",0,2);
        Map m8 = new Map("阎罗殿","绿色鬼火忽明忽暗，无数鬼差阴使肃立两边，正当中坐一青面獠牙身穿朱红官服鬼王，上有匾额：阎罗殿",1,2);
        Map m9 = new Map("蓬莱","岛上密布紫竹，上有仙鸟悠然盘旋，仙音不断，观音大士端坐在一金色莲花当中，宝相庄严",2,2);

        Map maps[][] = new Map[3][3];

        maps[0][0] = m1;
        maps[1][0] = m2;
        maps[2][0] = m3;
        maps[0][1] = m4;
        maps[1][1] = m5;
        maps[2][1] = m6;
        maps[0][2] = m7;
        maps[1][2] = m8;
        maps[2][2] = m9;

        System.out.println("初始化地图结束........");
        return maps;
    }

    //初始化玩家
    public static Player initPlayer(Map[][] maps)
    {
        System.out.println("初始化玩家开始........");
        Player p1 = new Player("李逍遥",1000,5,15,0,0);
        //先定义技能
        Skill s1 = new Skill("万剑齐飞","只见天地变色，风起云涌，无数把飞剑从天而降，直冲对方飞刺过去！",100,"m");
        Skill s2 = new Skill("火球术","一个炙热火球向前飞去，击中后直接炸开无数火花",11,"s");
        //定义技能池（技能哈希映射）
        HashMap<String,Skill> skills = new HashMap<>();
        skills.put("万剑齐飞",s1);
        skills.put("火球术",s2);
        //将技能赋给角色
        p1.setSkills(skills);
        System.out.println(p1.getName()+"获取["+s1.getName()+"] 技能成功！");
        //显示技能
        //通过hashmap 的 key 遍历，访问到其中的任意一个技能，然后将技能信息打印出来
        for(String s :p1.getSkills().keySet())
        {
            Skill skill =  p1.getSkills().get(s);
            skill.print();
            System.out.println(skill.getName()+"  技能对应的 key 是:"+s);
        }
        System.out.println("初始化玩家结束........");
        return p1;
    }
    //初始化怪物
    public static void initMonsters(Map[][] maps){
        System.out.println("初始化所有怪物开始........");
        Monster m1 = new Monster("树妖",500,8,10);
        //因为对象是引用类型，所以要多个同种怪物，必须进行拷贝，而非直接用 = 赋值，
        // 否则传递的是地址，操作的都是同一个对象
        Monster m2= m1.copy();
        Monster m3 = new Monster("花精",100,5,15);
        Monster m4 = m3.copy();
        Monster m5 = m3.copy();
        //都塞入花果山地图
        maps[2][0].addMoster(m1);
        maps[2][0].addMoster(m2);
        maps[2][0].addMoster(m3);
        maps[2][0].addMoster(m4);
        maps[2][0].addMoster(m5);
        //给天竺增加怪物
        maps[0][0].addMoster(m1);
        maps[0][0].addMoster(m2);
        maps[0][0].addMoster(m3);
        maps[0][0].addMoster(m4);
        maps[0][0].addMoster(m5);
        System.out.println("初始化所有怪物结束........");
    }
}
